#include "VulkanDebug.h"
#include "../Core/CoreGlobals.h"
#include "../Utils/LogUtil.h"

#if 0

PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTag = VK_NULL_HANDLE;
PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = VK_NULL_HANDLE;
PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = VK_NULL_HANDLE;
PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = VK_NULL_HANDLE;
PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = VK_NULL_HANDLE;

void VulkanDebug::Init()
{
	// The debug marker extension is not part of the core, so function pointers need to be loaded manually
	vkDebugMarkerSetObjectTag = reinterpret_cast<PFN_vkDebugMarkerSetObjectTagEXT>(vkGetDeviceProcAddr(GVulkanRHI->GetLogicalDevice(), "vkDebugMarkerSetObjectTagEXT"));
	vkDebugMarkerSetObjectName = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(vkGetDeviceProcAddr(GVulkanRHI->GetLogicalDevice(), "vkDebugMarkerSetObjectNameEXT"));
	vkCmdDebugMarkerBegin = reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(vkGetDeviceProcAddr(GVulkanRHI->GetLogicalDevice(), "vkCmdDebugMarkerBeginEXT"));
	vkCmdDebugMarkerEnd = reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(vkGetDeviceProcAddr(GVulkanRHI->GetLogicalDevice(), "vkCmdDebugMarkerEndEXT"));
	vkCmdDebugMarkerInsert = reinterpret_cast<PFN_vkCmdDebugMarkerInsertEXT>(vkGetDeviceProcAddr(GVulkanRHI->GetLogicalDevice(), "vkCmdDebugMarkerInsertEXT"));
}

void VulkanDebug::SetObjectName(uint64 object, VkDebugReportObjectTypeEXT objectType, const char* name)
{
	if (vkDebugMarkerSetObjectName != VK_NULL_HANDLE)
	{
		VkDebugMarkerObjectNameInfoEXT objectNameInfo{};
		objectNameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
		objectNameInfo.objectType = objectType;
		objectNameInfo.object = object;
		objectNameInfo.pObjectName = name;
		vkDebugMarkerSetObjectName(GVulkanRHI->GetLogicalDevice(), &objectNameInfo);
	}
}

void VulkanDebug::SetObjectTag(uint64 object, VkDebugReportObjectTypeEXT objectType, uint64 tagName, uint64 tagSize, const void* tag)
{
	if (vkDebugMarkerSetObjectTag != VK_NULL_HANDLE)
	{
		VkDebugMarkerObjectTagInfoEXT objectTagInfo{};
		objectTagInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT;
		objectTagInfo.objectType = objectType;
		objectTagInfo.object = object;
		objectTagInfo.tagName = tagName;
		objectTagInfo.tagSize = tagSize;
		objectTagInfo.pTag = tag;
		vkDebugMarkerSetObjectTag(GVulkanRHI->GetLogicalDevice(), &objectTagInfo);
	}
}

void VulkanDebug::BeginRegion(VkCommandBuffer cmdbuffer, const char* markerName, glm::vec4 color)
{
	if (vkCmdDebugMarkerBegin != VK_NULL_HANDLE)
	{
		VkDebugMarkerMarkerInfoEXT markerInfo{};
		markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
		memcpy(markerInfo.color, &color[0], sizeof(float) * 4);
		markerInfo.pMarkerName = markerName;
		vkCmdDebugMarkerBegin(cmdbuffer, &markerInfo);
	}
}

void VulkanDebug::Insert(VkCommandBuffer cmdbuffer, std::string markerName, glm::vec4 color)
{
	if (vkCmdDebugMarkerInsert != VK_NULL_HANDLE)
	{
		VkDebugMarkerMarkerInfoEXT markerInfo{};
		markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
		memcpy(markerInfo.color, &color[0], sizeof(float) * 4);
		markerInfo.pMarkerName = markerName.c_str();
		vkCmdDebugMarkerInsert(cmdbuffer, &markerInfo);
	}
}

void VulkanDebug::EndRegion(VkCommandBuffer cmdBuffer)
{
	if (vkCmdDebugMarkerEnd != VK_NULL_HANDLE)
	{
		vkCmdDebugMarkerEnd(cmdBuffer);
	}
}

#endif


void VulkanDebug::SetObjectName(uint64 object, VkDebugReportObjectTypeEXT objectType, const char* name)
{
	VkDebugMarkerObjectNameInfoEXT objectNameInfo{};
	objectNameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
	objectNameInfo.objectType = objectType;
	objectNameInfo.object = object;
	objectNameInfo.pObjectName = name;
	vkDebugMarkerSetObjectNameEXT(GVulkanRHI->GetLogicalDevice(), &objectNameInfo);
}

void VulkanDebug::SetObjectTag(uint64 object, VkDebugReportObjectTypeEXT objectType, uint64 tagName, uint64 tagSize, const void* tag)
{
	VkDebugMarkerObjectTagInfoEXT objectTagInfo{};
	objectTagInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT;
	objectTagInfo.objectType = objectType;
	objectTagInfo.object = object;
	objectTagInfo.tagName = tagName;
	objectTagInfo.tagSize = tagSize;
	objectTagInfo.pTag = tag;
	vkDebugMarkerSetObjectTagEXT(GVulkanRHI->GetLogicalDevice(), &objectTagInfo);
}

void VulkanDebug::BeginRegion(VkCommandBuffer cmdbuffer, const char* markerName, glm::vec4 color)
{
	VkDebugMarkerMarkerInfoEXT markerInfo{};
	markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
	memcpy(markerInfo.color, &color[0], sizeof(float) * 4);
	markerInfo.pMarkerName = markerName;
	vkCmdDebugMarkerBeginEXT(cmdbuffer, &markerInfo);
}

void VulkanDebug::Insert(VkCommandBuffer cmdbuffer, std::string markerName, glm::vec4 color)
{
	VkDebugMarkerMarkerInfoEXT markerInfo{};
	markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
	memcpy(markerInfo.color, &color[0], sizeof(float) * 4);
	markerInfo.pMarkerName = markerName.c_str();
	vkCmdDebugMarkerInsertEXT(cmdbuffer, &markerInfo);
}

void VulkanDebug::EndRegion(VkCommandBuffer cmdBuffer)
{
	vkCmdDebugMarkerEndEXT(cmdBuffer);
}
